/**
 * Copyright (c) 2020 Coder League
 * All rights reserved.
 *
 * File：MainService.java
 * History:
 *         2020年12月20日: Initially created, Chrise.
 */
package club.coderleague.cfss.service.main;

import java.util.List;

import javax.servlet.http.HttpSession;
import javax.validation.ValidationException;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import club.coderleague.cfss.dao.FunctionDao;
import club.coderleague.cfss.dao.UserDao;
import club.coderleague.cfss.domain.beans.UserSession;
import club.coderleague.cfss.domain.beans.VercodeBound;
import club.coderleague.cfss.domain.entities.Functions;
import club.coderleague.cfss.domain.entities.Users;
import club.coderleague.cfss.exceptions.RequestProcessInfoException;
import club.coderleague.cfss.exceptions.RequestProcessWarnException;
import club.coderleague.cfss.service.interfaces.AliyunInterfaceService;
import club.coderleague.cfss.util.HttpServletUtil;

/**
 * 主界面服务。
 * @author Chrise
 */
@Service
public class MainService {
	@Autowired
	private FunctionDao functionDao;
	@Autowired
	private UserDao userDao;
	@Autowired
	private PasswordEncoder passwordEncoder;
	@Autowired
	private AliyunInterfaceService aiService;
	
	/**
	 * 根据父级功能主键和功能类型查询已授权功能。
	 * @author Chrise 2020年12月20日
	 * @param parentfunc 父级功能主键。
	 * @param functype 功能类型。
	 * @return 已授权功能。
	 */
	public List<Functions> findAuthorizationByParentfuncAndFunctype(Long parentfunc, List<Integer> functype) {
		return this.functionDao.findAuthorizationByParentfuncAndFunctype(parentfunc, functype);
	}
	
	/**
	 * 修改当前登录用户密码。
	 * @author Chrise 2020年12月22日
	 * @param oldpassword 原密码。
	 * @param newpassword 新密码。
	 * @param source 修改来源（true：登录，false：主页）。
	 */
	public void updatePassword(String oldpassword, String newpassword, boolean source) {
		if (StringUtils.isBlank(oldpassword)) {
			throw new ValidationException("原密码不能为空");
		}
		if (StringUtils.isBlank(newpassword)) {
			throw new ValidationException("新密码不能为空");
		}
		
		if (source) {	// 登录修改密码
			HttpSession session = HttpServletUtil.getHttpSession();
			if (session == null) throw new RequestProcessWarnException("登录信息不存在");
			Long userid = (Long)session.getAttribute(Users.class.getTypeName());
			if (userid == null) throw new RequestProcessWarnException("登录信息不存在");
			
			Users user = this.userDao.getOne(userid);
			if (!this.passwordEncoder.matches(oldpassword, user.getLoginpassword())) {
				throw new RequestProcessInfoException("原密码错误");
			}
			user.setLoginpassword(this.passwordEncoder.encode(newpassword));
			user.setInitpassword(false);
			
			UserSession us = this.userDao.queryUserSession(userid);
			session.setAttribute(UserSession.SESSION_KEY, us);
			session.removeAttribute(Users.class.getTypeName());
		} else {		// 主页修改密码
			UserSession us = HttpServletUtil.getUserSession();
			if (us == null) {
				throw new RequestProcessWarnException("用户会话不存在");
			}
			Users user = this.userDao.getOne(us.getId());
			if (!this.passwordEncoder.matches(oldpassword, user.getLoginpassword())) {
				throw new RequestProcessInfoException("原密码错误");
			}
			user.setLoginpassword(this.passwordEncoder.encode(newpassword));
			
			HttpSession session = HttpServletUtil.getHttpSession();
			us.setPassword(user.getLoginpassword());
			session.setAttribute(UserSession.SESSION_KEY, us);
		}
	}
	
	/**
	 * 修改当前登录用户电话。
	 * @author Chrise 2020年12月22日
	 * @param userphone 手机号。
	 * @param session 会话对象。
	 * @param us 用户会话。
	 * @return 修改结果。
	 */
	public String updateUserphone(String userphone, HttpSession session, UserSession us) {
		if (this.userDao.existsByLoginnameOrUserphoneNotEntityid(null, userphone, us.getId())) return "手机号已占用！";
		
		Users user = this.userDao.getOne(us.getId());
		user.setUserphone(userphone);
		
		us.setUserphone(userphone);
		session.setAttribute(UserSession.SESSION_KEY, us);
		
		return null;
	}
	
	/**
	 * 修改当前登录用户电话。
	 * @author Chrise 2020年12月22日
	 * @param userphone 手机号。
	 * @param vercode 验证码。
	 * @param session 会话对象。
	 * @param us 用户会话。
	 * @return 修改结果。
	 */
	public String updateUserphone(String userphone, String vercode, HttpSession session, UserSession us) {
		VercodeBound cached = this.aiService.getCachedVercode(session.getId());
		if (cached == null) return "验证码已失效！";
		
		if (!cached.getPhone().equals(userphone)) return "手机号不匹配！";
		if (!cached.getCode().equals(vercode)) return "验证码错误！";
		
		this.aiService.clearCache(session.getId());
		
		if (this.userDao.existsByLoginnameOrUserphoneNotEntityid(null, userphone, us.getId())) return "手机号已占用！";
		
		Users user = this.userDao.getOne(us.getId());
		user.setUserphone(userphone);
		
		us.setUserphone(userphone);
		session.setAttribute(UserSession.SESSION_KEY, us);
		
		return null;
	}
	
	/**
	 * 修改当前登录用户登录名。
	 * @author Chrise 2020年12月22日
	 * @param newloginname 新登录名。
	 */
	public void updateLoginname(String newloginname) {
		if (StringUtils.isBlank(newloginname)) {
			throw new ValidationException("登录名不能为空");
		}
		UserSession us = HttpServletUtil.getUserSession();
		if (us == null) {
			throw new RequestProcessWarnException("用户会话不存在");
		}
		if (this.userDao.existsByLoginnameOrUserphoneNotEntityid(newloginname, null, us.getUserid())) {
			throw new RequestProcessWarnException("登录名已存在");
		}
		Users user = this.userDao.getOne(us.getId());
		user.setLoginname(newloginname);
		
		HttpSession session = HttpServletUtil.getHttpSession();
		us.setLoginname(newloginname);
		session.setAttribute(UserSession.SESSION_KEY, us);
	}
}
